home *** CD-ROM | disk | FTP | other *** search
/ isnet Internet / Isnet Internet CD.iso / prog / hiz / 09 / 09.exe / adynware.exe / perl / lib / adynware_server.pm < prev    next >
Encoding:
Perl POD Document  |  2000-05-01  |  22.5 KB  |  671 lines

  1. package adynware_server;
  2. require 5.004;
  3. use strict;
  4. use diagnostics;
  5. use adynware::utility;
  6. use adynware::q_count;
  7. use IO::Select;
  8. use IO::Socket;
  9. use IO::File;
  10. use adynware::utility_file;
  11.  
  12. my $idle__NOT                        =50;
  13. my $idle__DO_BACKGROUND_TASKS                =51;
  14. my $idle__TOTALLY                    =52;
  15.  
  16. my $HTMLHEADER = "HTTP/1.0 200 OK\nContent-type: text/html\n\n";
  17.  
  18. my $state_AWAITING_RESPONSE                =2;
  19.  
  20. my $server__applicationName = "uninitialized_applicationName";
  21. my $server__applicationVersion = "0.0";
  22. my $__bufferAll = 0;
  23. my %__buffers = ();
  24. my $server__customerID = 71256;
  25. my %server__handleStates = ();
  26. my $server__idleState = $idle__NOT;
  27. my $server__internetAvailable = 1;
  28. my $server__js = "";
  29. #my $server__massageUserPerl = 1;
  30. my $__memory = "";
  31. my $server__mostRecentDocument = "";
  32. my @server__noProxy = ();
  33. my $server__port = 38201;
  34. my $server__proxyServer = "";
  35. my $server__proxyPort = 80;
  36. my $__relay = 1;
  37. my $server__select = 0;
  38. my $server__shutdownRequested = 0;
  39. my $server__userFactory = 0;
  40. my %server__users = ();
  41. my $server__verbose = 0;
  42. my $server__aRequestHasBeenSeen = 0;
  43. my $__controllerPort = 0;
  44.  
  45. #sub InternetAvailable
  46. #{
  47. #        my($host) = @_;
  48. #        my @tmp = gethostbyname($host);
  49. #        my @address = unpack('C4', $tmp[4]);
  50. #        return ("$address[0].$address[1].$address[2].$address[3]" ne "127.0.0.1");
  51. #}
  52. #
  53. sub ShutdownAtNextCheckPoint
  54. {
  55.         $server__shutdownRequested = 1;
  56. }
  57.  
  58. sub LogState
  59. {
  60.         utility::LogState(@_);
  61. }
  62.  
  63. sub Init
  64. {
  65.         my($programName, $user, $applicationName, $applicationVersion) = @_;
  66.         die "incomplete invocation of adynware_server::Init" unless defined $applicationVersion;
  67.                 
  68.         #        $__memory = "";
  69.         #        for (my $j=0; $j<1000; $j++)
  70.         #        {
  71.         #                $__memory .= "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
  72.         #        }
  73.         
  74.                 
  75.         $server__userFactory = $user;
  76.                         
  77.         $server__applicationName = $applicationName;
  78.         $server__applicationVersion = $applicationVersion;
  79.                         
  80.         my $deleteSource = 0;
  81.                         
  82.         my $logFileName = undef;
  83.                 
  84.         utility::Init($programName, $server__verbose, undef, undef, undef, undef);
  85.         while (@ARGV)
  86.         {
  87.                 $_ = shift @ARGV;
  88.                 if (/^-bufferAll$/)
  89.                 {
  90.                         $__bufferAll = 1;
  91.                 }
  92.                 elsif (/^-controllerPort$/)
  93.                 {
  94.                         $__controllerPort = shift @ARGV;
  95.                 }
  96.                 elsif (/^-customerID$/)
  97.                 {
  98.                         $server__customerID = shift @ARGV;
  99.                 }
  100.                 elsif (/^-forms1to25$/)
  101.                 {
  102.                         Decorate::listFormsFirst();
  103.                 }
  104.                 elsif (/^-log$/)
  105.                 {
  106.                         $logFileName = shift @ARGV;
  107.                                                                                                 
  108.                 }
  109.                 elsif (/^-logFast$/)
  110.                 { 
  111.                         utility::LogInMemory(1);
  112.                 }
  113.                 elsif (/^-norelay$/)
  114.                 {
  115.                         $__relay = 0;
  116.                 } 
  117.                 elsif (/^-noProxy$/)
  118.                 {
  119.                         @server__noProxy = utility::constructIPMaskSet(shift @ARGV);
  120.                                                 
  121.                         #foreach my $address (@server__noProxy)
  122.                         #{
  123.                         #printf "noProxy(%s)\n", unpack("H8", $address);
  124.                         #}
  125.                 }
  126.                 elsif (/^-port$/)
  127.                 {
  128.                         $server__port = shift @ARGV;
  129.                 }
  130.                 elsif (/^-proxyPort$/)
  131.                 {
  132.                         print "error: -proxyPort option is only valid AFTER specifying the -proxyServer option\n" unless $server__proxyServer;
  133.                         $server__proxyPort = shift @ARGV;
  134.                 }
  135.                 elsif (/^-proxyServer$/)
  136.                 {
  137.                         $server__proxyServer = shift @ARGV;
  138.                 }
  139.                 elsif (/^-superscriptColor$/)
  140.                 {
  141.                         my $color = shift @ARGV;
  142.                         utility::Die "-superscriptColor must be followed by an HTML color" unless defined $color and $color;
  143.                         Decorate::setColor($color);
  144.                 }
  145.                 elsif (/^-superscriptExpression$/)
  146.                 {
  147.                         utility::Log("redefining superscript expression");
  148.                         my $expression = shift @ARGV;
  149.                         utility::Die "-superscriptExpression must be followed by an HTML expression for superscripts (e.g., \"<FONT color=red><B><SUP>%d</SUP></B></FONT>\")" unless defined $expression and $expression;
  150.                         if ($expression =~ s/^(['"])//)
  151.                         {
  152.                                 my $limit = $1;
  153.                                 my $tmp;
  154.                                 my $terminated = 0;
  155.                                 while ($tmp = shift @ARGV)
  156.                                 {
  157.                                         $expression .= " $tmp";
  158.                                         utility::Log("expression is $expression");
  159.                                         if ($expression =~ s/$limit$//)
  160.                                         {
  161.                                                 $terminated = 1;
  162.                                                 last;
  163.                                         } 
  164.                                 }
  165.                                 utility::Die "unterminated $limit on the command line" unless $terminated;
  166.                                                                 
  167.                                 utility::Log("expression finally is $expression");
  168.                         } 
  169.                         Decorate::setSuperscriptExpression($expression);
  170.                 }
  171.                 elsif (/^-unique$/)
  172.                 {
  173.                         Decorate::setUnique(1);
  174.                 }
  175.                 elsif (/^-v$/)
  176.                 {
  177.                         $server__verbose = shift @ARGV;
  178.                 }
  179.                 elsif (/^-unlink$/)
  180.                 {
  181.                         $deleteSource = 1;
  182.                 }
  183.                 elsif (/^-version$/)
  184.                 {
  185.                         print "$server__applicationName $server__applicationVersion, Copyright 1998, Adynware Corp.\n";
  186.                         exit(0);
  187.                 }
  188.                 else
  189.                 {
  190.                         print "not acting on command line argument $_";
  191.                 }
  192.         }
  193.         if ($deleteSource)
  194.         {
  195.                 unlink($0);
  196.         }
  197.         utility::Spit($server__port); #  must precede the log file creation
  198.                         
  199.                 
  200.         if (defined $logFileName)
  201.         {
  202.                 my $logFile;
  203.                 if ($logFile = new IO::File("> $logFileName"))
  204.                 {
  205.                         utility::Log("logging to $logFileName");
  206.                         select($logFile);
  207.                 }
  208.                 else
  209.                 {
  210.                         utility::Log("initialization error: could not create $logFileName");
  211.                 }
  212.         }
  213.                                                 
  214.         utility::Init($programName, $server__verbose, undef, $server__port, $server__proxyServer, $server__proxyPort);
  215.                 
  216.         utility::Log("$server__applicationName $server__applicationVersion listening to port $server__port");
  217.         utility::Log("$server__applicationName forwarding queries to $server__proxyServer:$server__proxyPort") if $server__proxyServer;
  218.         $| = 1; #because I am logging to stdout (or the log file, which is selected as stdout)
  219. }
  220.  
  221. sub CleanupAndExit
  222. {
  223.         exit(0);
  224. }
  225.  
  226.  
  227.  
  228. sub ErrorMessageToBrowser 
  229. {
  230.         my($fd, $error, $message) = @_;
  231.                                                                                                                                 
  232.         my $s = "HTTP/1.0 404 OK\n" .
  233.         "Content-type: text/html\n\n" .
  234.         "<HTML><script language=javascript>alert(\"" .
  235.         $message .
  236.         "\");</script></HTML>\n";
  237.                 
  238.         print $fd $s;
  239.         CloseClient($fd, "");
  240. }
  241.  
  242. sub PrintToClient
  243. {
  244.         my($client, $data, $target) = @_;
  245.         my $length = length($data);
  246.         utility::Log("PrintToClient($client, $length, $target) called") if $server__verbose >= 9;
  247.         return 0 unless $client;                       
  248.                 
  249.                 
  250.         if (defined $__buffers{$client})
  251.         {
  252.                 $__buffers{$client} .= $data;
  253.                 return 1;
  254.         }
  255.         
  256.         my $result = print $client $data;
  257.         
  258.         $result = "undefined" unless defined $result;
  259.         utility::Log("PrintToClient returned $result") if $server__verbose >= 9;
  260.         if (!$result)
  261.         {
  262.                 CloseClient($client, $target);
  263.                 return 0;
  264.         }
  265.         return 1;
  266. }
  267.  
  268.  
  269. sub CloseClient
  270. {
  271.         my($client, $target) = @_;
  272.         if ($client)
  273.         {
  274.                 my $buffer = delete($__buffers{ $client});
  275.                 print $client $buffer if defined $buffer;
  276.                 
  277.                 #utility::Log("close client:$client $target");
  278.                 close $client;
  279.         }
  280.         q_count::DecrementQueryCount($target);                                
  281. }
  282.  
  283. sub SendRequest
  284. {
  285.         my($target, $machine, $port, $clientRequest, $client) = @_;
  286.                         
  287.         if ($server__proxyServer)
  288.         {
  289.                 if (!utility::IPInMaskSet($machine, @server__noProxy))
  290.                 {
  291.                         $machine = $server__proxyServer;
  292.                         $port = $server__proxyPort;
  293.                 }
  294.         } 
  295.                         
  296.     utility::Log("adynware_server::SendRequest($target, $machine, $port)") if $server__verbose >= 9;
  297.         my $server = IO::Socket::INET->new(PeerAddr => $machine, PeerPort => $port, Proto => 'tcp');
  298.         if (!$server)
  299.         {
  300.                 $server__internetAvailable = 0;
  301.                 return 0;
  302.         }
  303.         $server__internetAvailable = 1;
  304.                 
  305.         $clientRequest =~ s/^Accept-Encoding: gzip\r?\n//im;
  306.         
  307.         utility::SendRequest( $server, $clientRequest);
  308.         $server__select->add($server);
  309.         q_count::IncrementQueryCount($target);
  310.         return $server;
  311. }
  312.    
  313. sub DocumentFinish
  314. {
  315.         my($userKey, $target) = @_;
  316.         my $user = delete($server__users{$userKey});
  317.         utility::Log("document finish($target): $user for $userKey") if $server__verbose >= 9;
  318.         return "" unless $user;
  319.                                                 
  320.         my $stuff = $user->DocumentFinish();
  321.                                                         
  322.         if ($server__js)
  323.         {
  324.                 $stuff .= "<script JavaScript> $server__js</script>"; 
  325.                 $server__js = "";
  326.         }
  327.         utility::Log("document finish: end string:$stuff") if $server__verbose >= 9;
  328.         return $stuff;
  329. }
  330.  
  331. sub ReadResponseChunk
  332. {
  333.     my($server, $client, $contentType, $target, $firstChunk) = @_;
  334.     my $buffer = undef;
  335.     if ($firstChunk)
  336.     {
  337.         my $header = utility::ReadFirstChunk("read-chunk", $server, $target, \$buffer,\$contentType,undef,1,1);
  338.         if (!defined $header)
  339.         {
  340.             ErrorMessageToBrowser($client, 500, "There was no response.  $target could be down<br>or is not responding.");
  341.             return undef;
  342.         }
  343.                                                                         
  344.         if ($header !~ m{HTTP/\d+.\d+\s+(\d+)}i)
  345.         {
  346.             utility::Log("error: adynware server: could not extract status from $header");
  347.         }
  348.         else
  349.         {
  350.             my $status = $1;
  351.             utility::Log("adynware server: got status $status for $target from $header") if $server__verbose >= 9;
  352.             if ($status==302)
  353.             {
  354.                 my $filter = $server__userFactory->Create("http://$target", $status);
  355.                 if ($header =~ m{^Location:\s*(.*)}im)
  356.                 {
  357.                     my $newLocation = $1;
  358.                     $filter->Redirect($target, $newLocation);
  359.                     $contentType = "redirect";
  360.                 }
  361.             }
  362.             elsif ($contentType =~ m{text/html.*})
  363.             {
  364.                 $server__users{$client} = $server__userFactory->Create("http://$target", $status);
  365.                 $header .= $server__users{$client}->DocumentStart(); 
  366.             }
  367.         }
  368.         utility::Log("writing header:'$header'") if $server__verbose >= 9;
  369.         return undef unless PrintToClient($client, $header, $target);
  370.     }
  371.                                                                                                     
  372.     my $n = undef;
  373.     if (defined $buffer and $buffer)
  374.     {
  375.         $n = length($buffer);
  376.     }
  377.     elsif (!$firstChunk)
  378.     {
  379.         $n = utility::Read("ReadResponseChunk", $server, \$buffer, 9184); 
  380.     }
  381.                                                                                                     
  382.     if (defined $n)
  383.     {
  384.         if ($n)
  385.         {
  386.             if ($contentType =~ m{text/html.*})
  387.             {
  388.                 utility::Log("html chunk ($__relay) $client $target:$buffer\nEOD") if $server__verbose >= 9;
  389.                 $server__users{$client}->DocumentChunk(\$buffer);
  390.                 utility::Log("html processed $client $target:$buffer\nEOD") if $server__verbose >= 9;
  391.                 if (!$__relay and !defined $__buffers{$client} and ($__bufferAll or $buffer =~ /<\s*iframe\b/i))
  392.                 {
  393.                     $__buffers{$client} = "";
  394.                     utility::Log("buffering $target up to prevent deadlock") if $server__verbose >= 9;
  395.                 } 
  396.             }
  397.             elsif ("text/plain" eq $contentType and $server__verbose >= 90)
  398.             {
  399.                 my $s;
  400.                 print "substring is ",substr($buffer, 0, 3);
  401.                 if (substr($buffer, 0, 3) eq "GIF")
  402.                 {
  403.                     $s = "GIF image";
  404.                 }
  405.                 else
  406.                 {
  407.                     $s = "$buffer\nEOD";
  408.                 } 
  409.                 utility::Log("text chunk $client $target:$s");
  410.             }
  411.             return undef unless PrintToClient($client, $buffer, $target);
  412.             utility::Log("done: $n bytes\n") if $server__verbose >= 9;
  413.         }
  414.         else
  415.         {
  416.             if ($contentType =~ m{text/html.*})
  417.             {
  418.                 $buffer = DocumentFinish($client, $target);
  419.                 utility::Log("html chunk: processed:$buffer\nEOD") if $server__verbose >= 9;
  420.                 return undef unless PrintToClient($client, $buffer, $target);
  421.             }
  422.             CloseClient($client, $target);
  423.             return undef;
  424.         }                
  425.     }                
  426.     return [$state_AWAITING_RESPONSE, $server, $client, $contentType, $target, 0, undef];
  427. }
  428.  
  429. sub Idle
  430. {
  431.     my($timeSinceLastRequest) = @_;
  432.     utility::LogFlush();
  433.         
  434.     if ($__controllerPort and $server__aRequestHasBeenSeen and $timeSinceLastRequest > 120)
  435.     {
  436.         # tell webrelay to restart    
  437.         my $server = IO::Socket::INET->new(PeerAddr => 127.0.0.1, PeerPort => $__controllerPort, Proto => 'tcp');
  438.         if (!$server)
  439.         {
  440.             print "could not connect to 127.0.0.1:$__controllerPort\n";
  441.             return;
  442.         }
  443.         print "sending 'restart' to 127.0.0.1:$__controllerPort\n";
  444.         print $server "restart";
  445.         close $server;
  446.                 
  447.         $timeSinceLastRequest = 0; # avoid an immediate repetition of this request
  448.     } 
  449. }
  450.  
  451. sub IsDocument
  452. {
  453.     my($fileName) = @_;
  454.     return ($fileName =~ m{(\.html?\b.*|\.cgi\b.*|/)$}i);
  455. }
  456.  
  457. sub DoCommand 
  458. {
  459.     my ($client, $clientRequest) = @_;
  460.     utility::Log("DoCommand($client, $clientRequest)...") if $server__verbose >= 3; 
  461.                                     
  462.     if (!defined $clientRequest or $clientRequest !~ /([^\n]*)\n/)
  463.     { 
  464.         ErrorMessageToBrowser($client, 500, "network error: no client line 1 in header");
  465.         return 1;
  466.     }
  467.     my $clientFirstLine = $1;                                                                                                      
  468.     if ($clientFirstLine !~ /^(\S+) (.*) (\S+)$/)
  469.     {
  470.         ErrorMessageToBrowser($client, 500, "network error: can't parse client line 1 ($clientFirstLine)"); 
  471.         return 1;
  472.     }
  473.     my($command, $protocolAndMachineAndPortAndFile, $proto) = ($1, $2, $3);
  474.                                                                                                                                                                                     
  475.     if ($command !~ /(GET|POST)/i)
  476.     {
  477.         ErrorMessageToBrowser($client, 500, "Supporting only GET, POST, not '$command' (from $clientFirstLine)");
  478.         return 1;
  479.     }
  480.                             
  481.     if ($protocolAndMachineAndPortAndFile !~ m<^(\w+)://([^:/]*)(:(\d+))?($|/(.*)$)> ) 
  482.     {
  483.         ErrorMessageToBrowser($client, 500, "Can't parse $protocolAndMachineAndPortAndFile from $clientRequest");
  484.                 return 1;
  485.         }
  486.         my($protocol, $machine, $port, $file) = ($1, $2, $4, "/$6");
  487.         if ($protocol !~ /http/i)
  488.         {
  489.                 ErrorMessageToBrowser($client, 500, "must be http ($protocol illegal)");
  490.                 return 1;
  491.         }
  492.         $port = 80 unless defined $port;
  493.         
  494.         my $target;
  495.         if ($port==80) 
  496.         {
  497.                 $target = $machine . $file;                        
  498.         } 
  499.         else
  500.         {
  501.                 $target = $machine . ":$port" . $file;                        
  502.         }
  503.         
  504.         
  505.         if (!$server__proxyServer)
  506.         {
  507.                 $clientRequest =~ s{http://[^/]*}{};  # remove protocol and host from initial line
  508.         }
  509.                 
  510.         if ($target =~ m{__adynware__/([^/]+)/(.*)})
  511.         {
  512.                 return utility::HandleAdynware($client, $1, $2);
  513.                         } 
  514.                         
  515.         if ($command =~ /get/i)
  516.         {
  517.                 if (IsDocument($file))
  518.                 {
  519.                         $server__mostRecentDocument = $target;
  520.                         $clientRequest =~ s/^(If-Modified-Since:.*);.*/$1/im;
  521.                 }
  522.         }
  523.         my $server = SendRequest($target, $machine, $port, $clientRequest, $client);
  524.         if (!$server)
  525.         {
  526.                 ErrorMessageToBrowser($client, 500, "Can't Connect to $machine:$port");
  527.                 return 1;
  528.         }
  529.         $server__handleStates{$server} = [ $state_AWAITING_RESPONSE, $server, $client, undef, $target, 1 ];
  530.         utility::Log("$server connected: $clientRequest") if $server__verbose >= 8;
  531.         return 0;
  532. }
  533.  
  534.  
  535.  
  536.  
  537. sub PopHash
  538. {
  539.         my($hashReference) = @_;
  540.         my @keys = keys %$hashReference;
  541.         return undef unless scalar(@keys);
  542.         return delete($$hashReference{ $keys[0] });
  543. }
  544.  
  545.  
  546.  
  547. sub DoMain()
  548. {
  549.     my $requests = IO::Socket::INET->new(LocalPort => $server__port, Proto => 'tcp', Listen => SOMAXCONN, Reuse => 1);
  550.                     
  551.     utility::Die("$server__applicationName could not allocate a socket.  Is there nonstandard networking software on this machine?") unless defined $requests and $requests;
  552.                     
  553.     $server__select = new IO::Select($requests);
  554.                                                                                     
  555.     my @ready;
  556.     my $delay = 6;
  557.     my $timeSinceLastRequest = 0;
  558.     for (my $idleCount = 0;; $idleCount = q_count::GuardAgainstCorruptQueryCount($idleCount))
  559.     {
  560.         CleanupAndExit() if $server__shutdownRequested;
  561.                                                                         
  562.         my $error = 0;
  563.         @ready = $server__select->can_read(0); 
  564.         if (!scalar(@ready))
  565.         {
  566.             if (@ready = $server__select->has_error(0))
  567.             {
  568.                 $error = 1;
  569.                 utility::Log("Main: error on $ready[0]");
  570.             }
  571.         }
  572.         utility::Log("Main: select: activity on " . scalar(@ready) . " handles (" . q_count::GetQueryCountString() . ")") if $server__verbose >= 10;
  573.         if (scalar(@ready))
  574.         {
  575.             $idleCount = 0;
  576.         }
  577.         else
  578.         { 
  579.             @ready = $server__select->can_read($delay);
  580.         }
  581.                                                         
  582.         if (scalar(@ready))
  583.         {
  584.             $server__idleState = $idle__NOT;
  585.             $timeSinceLastRequest = 0;
  586.         }
  587.         else
  588.         {
  589.             $timeSinceLastRequest += $delay;
  590.             Idle($timeSinceLastRequest);
  591.         }
  592.                                         
  593.                                                                         
  594.         my $handle;
  595.         foreach $handle (@ready)
  596.         {
  597.             $idleCount = 0;
  598.             if ($handle==$requests)
  599.             {
  600.                 utility::Die "problems on the request socket:$!" if $error;
  601.                 utility::Log("Main: New request: accepting...") if $server__verbose >= 8;
  602.                 $server__aRequestHasBeenSeen = 1;
  603.                 my $client = $requests->accept(); 
  604.                 #my($savedSelectedFile) = select($client); $| = 1; select($savedSelectedFile); 
  605.                 if (defined $client)
  606.                 {
  607.                     if (DoCommand($client, utility::ReadHeader("Main", $client)))
  608.                     {
  609.                         close $client;
  610.                         utility::Log("Main: New request dealt with") if $server__verbose >= 8;
  611.                     }
  612.                 }
  613.                 else
  614.                 {
  615.                     utility::Log("Main: got an undefined handle from accept()");
  616.                 }
  617.             }
  618.                         else
  619.                         {
  620.                                 my $state = $server__handleStates{$handle};
  621.                                 LogState("read-ready handle", $handle, $state) if $server__verbose >= 8; 
  622.                                 next if !defined $state;
  623.                                                                                                 
  624.                                 my $whatNow = shift(@$state);
  625.                                 if ($error)
  626.                                 {
  627.                                         $state = undef;
  628.                                 }
  629.                                 elsif ($whatNow==$state_AWAITING_RESPONSE)
  630.                                 {
  631.                                         $state = ReadResponseChunk(@$state);
  632.                                 }
  633.                                 else
  634.                                 {
  635.                                         LogState("bad op in Main", $handle, $state);
  636.                                         utility::Die("unexpected state in Main");
  637.                                 }
  638.                                                                                                 
  639.                                 if (defined $state)
  640.                                 {
  641.                                         LogState("post-read", $handle, $state) if $server__verbose >= 8;
  642.                                         $server__handleStates{$handle} = $state;
  643.                                 }
  644.                                 else
  645.                                 {
  646.                                         utility::Log("Main: dropping state for $handle") if $server__verbose >= 8;
  647.                                         delete($server__handleStates{$handle});
  648.                                         utility::Log("Main: post-read: " . $handle . " closing") if $server__verbose >= 8;
  649.                                         $server__select->remove($handle);
  650.                                         close $handle;
  651.                                 }
  652.                         }
  653.                 }
  654.                 utility::Log("Main: calling select...") if $server__verbose >= 10;
  655.         }
  656. }
  657.  
  658. sub Main
  659. {
  660.         eval
  661.         {
  662.                 DoMain();
  663.         };
  664.         utility::LogInMemory(0);
  665.         exit(0) unless ($@);
  666.         utility::Log("adynware_server: Main encountered trouble: $@");
  667.         utility::Die("adynware_server: $@");
  668. }
  669.  
  670. 1;
  671.